﻿namespace UHIDLInk
{
    /// <summary>
    /// 构建Windows命令行版本的键盘数据包的示例
    /// </summary>
    public class FramePackageCMDBuilder
    {
        /// <summary>
        /// 根据ConsoleKeyInfo构建键盘按下数据包
        /// </summary>
        /// <param name="cki">控制台按键信息</param>
        /// <returns>键盘按下数据包</returns>
        public static TransferProtocol.FramePackage BuildKeyDownFPFromCKI(ConsoleKeyInfo cki)
        {
            TransferProtocol.FramePackage FP = new()
            {
                // 设置命令码和数据长度
                FrameCMD = (byte)TransferProtocol.Commands.CMD_SEND_KB_GENERAL_DATA,
                FrameLEN = 0x08
            };
            byte controlKeyStatus = 0x00;
            // 判断功能键状态并设置相应的位
            if ((cki.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control)
            {
                controlKeyStatus |= (1 << 0);
                Console.Write("Ctrl+");
            }
            if ((cki.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift)
            {
                controlKeyStatus |= (1 << 1);
                Console.Write("Shift+");
            }
            if ((cki.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt)
            {
                controlKeyStatus |= (1 << 2);
                Console.Write("Alt+");
            }
            FP.FrameDATA.Add(controlKeyStatus);
            byte keyByte;
            FP.FrameDATA.Add(0x00);
            // 将按键映射到相应的键码
            keyByte = Convert.ToByte(TransferProtocol.KeyToCodeMap[cki.Key][3], 16);
            FP.FrameDATA.Add(keyByte);
            // 填充剩余的字节
            for (int i = 0; i < 5; i++)
            {
                FP.FrameDATA.Add(0x00);
            }
            //Console.WriteLine(Utility.ByteArrayToHexString(FP.FullPackage));
            return FP;
        }

        /// <summary>
        /// 根据按下数据包构建按键抬起数据包
        /// </summary>
        /// <param name="KeyDownFP">按下数据包</param>
        /// <returns>按键抬起数据包</returns>
        public static TransferProtocol.FramePackage BuildKeyUpFromFPFromFP(TransferProtocol.FramePackage KeyDownFP)
        {
            int dataC = KeyDownFP.FrameDATA.Count;
            KeyDownFP.FrameDATA.Clear();
            // 将数据包中的数据清零
            for (int i = 0; i < dataC; i++)
            {
                KeyDownFP.FrameDATA.Add(0x00);
            }
            return KeyDownFP;
        }

        /// <summary>
        /// 构建鼠标移动数据包
        /// </summary>
        /// <param name="L">左键是否按下</param>
        /// <param name="M">中键是否按下</param>
        /// <param name="R">右键是否按下</param>
        /// <param name="x">X轴移动距离，从-127到127，0表示不动</param>
        /// <param name="y">Y轴移动距离，从-127到127，0表示不动</param>
        /// <param name="scroll">滚轮移动距离，从-127到127，0表示不动</param>
        /// <returns>鼠标移动数据包</returns>
        public static TransferProtocol.FramePackage BuildMouseMotion(bool L, bool R, bool M, int x, int y, int scroll)
        {
            TransferProtocol.FramePackage FP = new()
            {
                FrameCMD = (byte)TransferProtocol.Commands.CMD_SEND_MS_REL_DATA,
                FrameLEN = 0x05
            };
            FP.FrameDATA.Add(0x01);
            byte mouseKeys = 0x00;
            // 判断鼠标按键状态并设置相应的位
            if (L)
            {
                mouseKeys |= (1 << 0);
            }
            if (R)
            {
                mouseKeys |= (1 << 1);
            }
            if (M)
            {
                mouseKeys |= (1 << 2);
            }
            FP.FrameDATA.Add(mouseKeys);
            byte xmove = 0x00;
            byte ymove = 0x00;
            byte smove = 0x00;
            // 处理X轴移动距离
            if (x < 0 && x > -128)
            {
                xmove = (byte)(0x100 - (byte)Math.Abs(x));
            }
            else if (x >= 0 && x < 128)
            {
                xmove = (byte)x;
            }
            FP.FrameDATA.Add(xmove);
            // 处理Y轴移动距离
            if (y < 0 && y > -128)
            {
                ymove = (byte)(0x100 - (byte)Math.Abs(y));
            }
            else if (y >= 0 & y < 128)
            {
                ymove = (byte)y;
            }
            FP.FrameDATA.Add(ymove);
            // 处理滚轮移动距离
            if (scroll < 0 && scroll > -128)
            {
                smove = (byte)(0x100 - (byte)Math.Abs(scroll));
            }
            else if (scroll >= 0 && scroll < 128)
            {
                smove = (byte)scroll;
            }
            FP.FrameDATA.Add(smove);

            return FP;
        }

        /// <summary>
        /// 构建鼠标停止数据包
        /// </summary>
        /// <param name="MouseMotionFP">鼠标相对运动数据包</param>
        /// <returns>鼠标停止数据包</returns>
        public static TransferProtocol.FramePackage BuildMouseStop(TransferProtocol.FramePackage MouseMotionFP)
        {
            int dataC = MouseMotionFP.FrameDATA.Count;
            MouseMotionFP.FrameDATA.Clear();
            MouseMotionFP.FrameDATA.Add(0x01);
            // 将数据包中的数据清零
            for (int i = 0; i < dataC - 1; i++)
            {
                MouseMotionFP.FrameDATA.Add(0x00);
            }
            return MouseMotionFP;
        }
    }
}